
#define NUM_CHOICES		5

#include "MainMenuState.h"

#include "../SGD Wrappers/SGD_AudioManager.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"
#include "../SGD Wrappers/SGD_InputManager.h"

#include "Game.h"
#include "BitmapFont.h"
#include "GameplayState.h"
#include "CreditsState.h"
#include "OptionsState.h"
#include "HowToPlayState.h"
#include "PickSaveSlotState.h"


/*static*/ MainMenuState* MainMenuState::GetInstance(void)
{
	static MainMenuState s_Instance;

	return &s_Instance;
}


void MainMenuState::Enter(void)
{
	SGD::GraphicsManager*	pGraphics	= SGD::GraphicsManager::GetInstance();
	SGD::AudioManager*		pAudio		= SGD::AudioManager::GetInstance();
	SGD::InputManager*		pInput		= SGD::InputManager::GetInstance();


	// Init
	clicked = false;
	selected = false;

	pInput->CheckForNewControllers();


	// Set background color
	//pGraphics->SetClearColor({ 50, 50, 50 });	// dark gray


	// Load assets
	m_hBackgroundImage	= pGraphics->LoadTexture("resource/graphics/Silent_Strike_menu.png");
	m_hTitleImage		= pGraphics->LoadTexture("resource/graphics/Silent_Strike.png");
	m_hReticleImage		= pGraphics->LoadTexture("resource/graphics/Reticle3.png", { 0, 0, 0 });
	m_hButton1			= pGraphics->LoadTexture("resource/graphics/rectangle1.png");
	m_hButton2			= pGraphics->LoadTexture("resource/graphics/rectangle2.png");
	m_hButtonSwitchSFX	= pAudio->LoadAudio("resource/audio/button_switch.wav");
	m_hMenuChangeSFX	= pAudio->LoadAudio("resource/audio/menu_change.wav");


	// Load volume levels
	OptionsState::GetInstance()->LoadVolumes();


	// setup selection rects
	selectonrects						= new SGD::Rectangle[NUM_CHOICES];
	stringlengths						= new int[NUM_CHOICES];

	int lengths[NUM_CHOICES] = { 9, 11, 7, 7, 4 };
	for (size_t i = 0; i < NUM_CHOICES; i++)
		stringlengths[i] = lengths[i];


	float	x_offset					= 16.0f;
	float	y_offset					= 15.0f;

	/*
	float	screenwidth					= Game::GetInstance()->GetScreenWidth();
	for (size_t i = 0; i < NUM_CHOICES; i++)
	{
		selectonrects[i].left	= (screenwidth - (stringlengths[i] * 32)) * 0.5f;
		selectonrects[i].left	-= x_offset;

		selectonrects[i].top	= starting_y + (y_offset * i);

		selectonrects[i].right	= selectonrects[i].left + (stringlengths[i] * 32);
		selectonrects[i].right	+= x_offset;

		selectonrects[i].bottom = selectonrects[i].top + 32.0f;
	}
	*/
	/*
	for (size_t i = 0; i < NUM_CHOICES; i++)
	{
		selectonrects[i].left	= starting_x;
		selectonrects[i].left	-= x_offset;

		selectonrects[i].top	= starting_y + (vertical_offset * i);
		selectonrects[i].top	-= y_offset;

		selectonrects[i].right	= selectonrects[i].left + (stringlengths[i] * 32);
		//selectonrects[i].right	+= x_offset;

		selectonrects[i].bottom = selectonrects[i].top + 32.0f;
	}
	*/
	for (size_t i = 0; i < NUM_CHOICES; i++)
	{
		selectonrects[i].left	= starting_x;
		selectonrects[i].left	-= x_offset;

		selectonrects[i].top	= starting_y + (vertical_offset * i);
		selectonrects[i].top	-= y_offset;

		selectonrects[i].right	= selectonrects[i].left + 256.0f;
		//selectonrects[i].right	+= x_offset;

		selectonrects[i].bottom = selectonrects[i].top + 32.0f;
		selectonrects[i].bottom	+= y_offset * 2;
	}
}
void MainMenuState::Exit(void)
 {
	SGD::GraphicsManager* pGraphics	= SGD::GraphicsManager::GetInstance();
	SGD::AudioManager*	  pAudio	= SGD::AudioManager::GetInstance();


	// Unload assets
	pGraphics->UnloadTexture(m_hBackgroundImage);
	pGraphics->UnloadTexture(m_hTitleImage);
	pGraphics->UnloadTexture(m_hReticleImage);
	pGraphics->UnloadTexture(m_hButton1);
	pGraphics->UnloadTexture(m_hButton2);
	pAudio->UnloadAudio(m_hButtonSwitchSFX);
	pAudio->UnloadAudio(m_hMenuChangeSFX);


	// deallocate dynamic arrays
	delete [] selectonrects;
	delete [] stringlengths;

	selectonrects = nullptr;
	stringlengths = nullptr;
}

bool MainMenuState::Input(void)
{
	SGD::InputManager*	pInput	= SGD::InputManager::GetInstance();
	SGD::AudioManager*	pAudio	= SGD::AudioManager::GetInstance();


	m_mPrevious = m_nCursor;


	// Press Escape to quit
	if( pInput->IsKeyPressed( SGD::Key::Escape ) == true/* || pInput->IsButtonDown(0, 2) == true */)
		m_nCursor = MenuItems::EXIT;
		//return false;	// quit game



	// keyboard input
	if (pInput->IsKeyPressed(SGD::Key::Down) == true /*|| pInput->GetLeftJoystick(0).y > 0*/ || pInput->IsDPadPressed(0, SGD::DPad::Down) == true)
	{
		m_mPrevious = m_nCursor;
		m_nCursor = m_nCursor + 1 < NUM_CHOICES ? m_nCursor + 1 : 0;
	}
	else if (pInput->IsKeyPressed(SGD::Key::Up) == true /*|| pInput->GetLeftJoystick(0).y < 0*/ || pInput->IsDPadPressed(0, SGD::DPad::Up) == true)
	{
		m_mPrevious = m_nCursor;
		m_nCursor = m_nCursor - 1 >= 0 ? m_nCursor - 1 : NUM_CHOICES - 1;
	}

	if (pInput->GetLeftJoystick(0).x != 0 || pInput->GetLeftJoystick(0).y != 0)
	//if (pInput->GetRightJoystick(0).x != 0 || pInput->GetRightJoystick(0).y != 0)
	{
		SGD::Point mpoint;
		mpoint.x = pInput->GetMousePosition().x + pInput->GetLeftJoystick(0).x;
		mpoint.y = pInput->GetMousePosition().y + pInput->GetLeftJoystick(0).y;

		if (mpoint.x < 0.0F)
			mpoint.x = 0.0F;
		if (mpoint.y < 0.0F)
			mpoint.y = 0.0F;
		if (mpoint.x > Game::GetInstance()->GetScreenWidth())
			mpoint.x = Game::GetInstance()->GetScreenWidth();
		if (mpoint.y > Game::GetInstance()->GetScreenHeight())
			mpoint.y = Game::GetInstance()->GetScreenHeight();

		pInput->SetMousePosition(mpoint);
	}




	// mouse input
	SGD::Point mousepos = pInput->GetMousePosition();
	bool collided = false;
	for (size_t i = 0; i < NUM_CHOICES; i++)
	{
		if (mousepos.IsWithinRectangle(selectonrects[i]) == true)
		{
			m_mPrevious = m_nCursor;
			m_nCursor = i;
			collided = true;
		}
	}
	selected = collided;

	if (pInput->IsKeyDown(SGD::Key::LButton) == true)
		clicked = true;
	else
		clicked = false;

	if (m_mPrevious != m_nCursor)
	{
		if (pAudio->IsAudioPlaying(m_hButtonSwitchSFX) == false)
			pAudio->PlayAudio(m_hButtonSwitchSFX, false);
	}



	// selection
	if (pInput->IsKeyPressed(SGD::Key::Enter) == true || (pInput->IsKeyReleased(SGD::Key::LButton) == true && selected == true) || pInput->IsButtonDown(0, 1) == true)
	{
		if (pAudio->IsAudioPlaying(m_hMenuChangeSFX) == false)
			pAudio->PlayAudio(m_hMenuChangeSFX, false);

		switch (m_nCursor)
		{
		case MenuItems::PLAY_GAME:
			{
				// ChangeState is VERY VOLATILE!!!
				//	- can only be safely called by a game state's Input, Update, or Render methods
				
				 Game::GetInstance()->AddState(PickSaveSlotState::GetInstance());

				// Exit this state immediately
				return true;	// keep playing in the new state
			}
			break;


		case MenuItems::HOW_TO_PLAY:
			{
				Game::GetInstance()->AddState(HowToPlayState::GetInstance());
				return true;
			}
			break;


		case MenuItems::OPTIONS:
			{
				Game::GetInstance()->AddState(OptionsState::GetInstance());
				return true;
			}
			break;


		case MenuItems::CREDITS:
			{
				Game::GetInstance()->AddState(CreditsState::GetInstance());
				return true;
			}
			break;


		case MenuItems::EXIT:
			{
				return false;	// quit the game
			}
			break;
		}
	}



	/*
	if (SGD::InputManager::GetInstance()->IsKeyPressed(SGD::Key::LButton) == true)
	{
		if (m_nCursor == MenuItems::PLAY_GAME)
		{
			Game::GetInstance()->RemoveState();
			Game::GetInstance()->AddState(GameplayState::GetInstance());
			return true;
		}
		else if (m_nCursor == MenuItems::PLAY_GAME)
		{
			Game::GetInstance()->AddState(HowToPlayState::GetInstance());
			return true;
		}
		else if (mousepos.IsWithinRectangle(selectonrects[MenuItems::OPTIONS]) == true)
		{
			Game::GetInstance()->AddState(OptionsState::GetInstance());
			return true;
		}
		else if (mousepos.IsWithinRectangle(selectonrects[MenuItems::CREDITS]) == true)
		{
			Game::GetInstance()->AddState(CreditsState::GetInstance());
			return true;
		}
		else if (mousepos.IsWithinRectangle(selectonrects[MenuItems::EXIT]) == true)
		{
			return false;	// quit the game
		}
	}
	*/



	return true;
}
void MainMenuState::Update(float elapsedTime)
{

}
void MainMenuState::Render(void)
{
	SGD::GraphicsManager* pGraphics = SGD::GraphicsManager::GetInstance();


	// Draw the background image
	pGraphics->DrawTexture(m_hBackgroundImage, { 0, 0 });


	// Draw the buttons
	/*
	====================================================================================================
	Calculating how much of the button's size you need to scale for it to appear inside of the menu text
	====================================================================================================

	Button width (b_width)	= 256
	Font width (f_width)	= 32
	Perfect string length	= 8			// 8 * 32 = 256


	=======================
	string.length < b_width
	=======================

	string			= "Exit"
	string.length	= 4


	curr_width	= string.length * f_width
	= 4 * 32
	= 128

	difference	= b_width - curr_width
	= 256 - 128
	= 128

	scale_diff	= difference / f_width
	= 128 / 32
	= 4

	scale_needed	= button_scale - (scale_diff / f_width)
	= 1 - (4 / 32)
	= 1 - (1/8)
	= 0.875

	=======================
	string.length > b_width
	=======================

	string			= "Play game"
	string.length	= 9


	curr_width	= string.length * f_width
	= 9 * 32
	= 288

	difference	= curr_width - b_width
	= 288 - 256
	= 32

	scale_diff	= difference / f_width
	= 32 / 32
	= 1

	scale_needed	= button_scale + (scale_diff / f_width)
	= 1 + (1/32)
	= 0.03125
	*/
	for (size_t i = 0; i < NUM_CHOICES; i++)
	{
		/*
		float start_width	= 256.0f;
		float button_scale	= 1.0f;
		float difference	= 0.0f;
		float scale_diff	= 1.0f;
		float scale_needed	= 1.0f;

		float curr_width	= static_cast<float>(stringlengths[i] * 32.0f);

		if (curr_width < start_width)
		{
			difference = start_width - curr_width;
		}
		else if (curr_width > start_width)
		{
			difference		= curr_width - start_width;
			scale_diff		= difference / 32.0f;
			scale_needed	= button_scale + (scale_diff / 32.0f);

			pGraphics->DrawTexture(m_hButton2, selectonrects[i].GetTopLeft(), 0.0f, {}, {}, { scale_needed, 1.0f });
		}
		*/
		pGraphics->DrawTexture(m_hButton2, selectonrects[i].GetTopLeft(), 0.0f, {}, {}, { 1.0f, 1.0f });
	}


	// Use the game's font
	const BitmapFont* pFont = Game::GetInstance()->GetFont();


	// Draw the game title
	/*
	// Display the game title centered at 4x scale
	const wchar_t* title1 = L"Silent Strike";	// 13
	pFont->Draw(title1, { (width - (13 * 32 * 2.0f)) / 2, 50 }, 2.0f, { 255, 255, 255 });
	*/
	// Align text based on window width
	float width			= Game::GetInstance()->GetScreenWidth();

	float titlescale			= 2.0f;
	float xpos					= (width - (256.0f * titlescale)) * 0.5f;
	SGD::Rectangle sourcerect	= { 3.0f, 76.0f, 256.0f, 174.0f };
	pGraphics->DrawTextureSection(m_hTitleImage, { xpos, 10 }, sourcerect, 0.0f, {}, { 255, 255, 0, 0 }, { titlescale, titlescale });



	// Display the menu options centered at 1x scale
	std::string menuitems[NUM_CHOICES] = { "Play Game", "How to Play", "Options", "Credits", "Exit" };

	float offset = 100.0F;


	/*
	pFont->Draw( "Play Game", { (width - (9 * 32))/2, starting_y + (offset * PLAY_GAME) },			// 300
	1.0f, {255, 0, 0} );
	pFont->Draw( "How to Play", { (width - (11 * 32))/2, starting_y + (offset * HOW_TO_PLAY) },	// 350
	1.0f, {255, 0, 0} );
	pFont->Draw( "Options", { (width - (7 * 32))/2, starting_y + (offset * OPTIONS) },			// 400
	1.0f, {255, 0, 0} );
	pFont->Draw( "Credits", { (width - (7 * 32))/2, starting_y + (offset * CREDITS) },			// 450
	1.0f, {255, 0, 0} );
	pFont->Draw( "Exit", { (width - (4 * 32))/2, starting_y + (offset * EXIT) },				// 500
	1.0f, {255, 0, 0} );
	*/
	/*
	pFont->Draw("Play Game",	{ starting_x, starting_y + (vertical_offset * PLAY_GAME) },		text_scale, { 255, 0, 0 });
	pFont->Draw("How to Play",	{ starting_x, starting_y + (vertical_offset * HOW_TO_PLAY) },	text_scale, { 255, 0, 0 });
	pFont->Draw("Options",		{ starting_x, starting_y + (vertical_offset * OPTIONS) },		text_scale, { 255, 0, 0 });
	pFont->Draw("Credits",		{ starting_x, starting_y + (vertical_offset * CREDITS) },		text_scale, { 255, 0, 0 });
	pFont->Draw("Exit",			{ starting_x, starting_y + (vertical_offset * EXIT) },			text_scale, { 255, 0, 0 });
	*/
	for (size_t i = 0; i < NUM_CHOICES; i++)
	{
		SGD::Color clr_normal	= { 255, 255, 0, 0 };		// red
		SGD::Color clr_selected = { 255, 255, 255, 255 };	// white
		SGD::Color clr_held		= { 255, 0, 0, 0 };			// black


		// not selected or colliding
		if (m_nCursor != i)
			pFont->Draw(menuitems[i].c_str(), { starting_x, starting_y + (vertical_offset * i) }, text_scale, clr_normal);

		// selected, not clicked, colliding
		else if (m_nCursor == i && clicked == false && selected == true)
			pFont->Draw(menuitems[i].c_str(), { starting_x, starting_y + (vertical_offset * i) }, text_scale, clr_selected);

		// selected, clicked, colliding
		else if (m_nCursor == i && clicked == true && selected == true)
			pFont->Draw(menuitems[i].c_str(), { starting_x, starting_y + (vertical_offset * i) }, text_scale, clr_held);

		// selected, clicked, not colliding
		else if (m_nCursor == i && clicked == true && selected == false)
			pFont->Draw(menuitems[i].c_str(), { starting_x, starting_y + (vertical_offset * i) }, text_scale, clr_selected);

		// selected, not clicked, not colliding
		else if (m_nCursor == i && clicked == false && selected == false)
			pFont->Draw(menuitems[i].c_str(), { starting_x, starting_y + (vertical_offset * i) }, text_scale, clr_selected);



		//pFont->Draw(menuitems[i].c_str(), { starting_x, starting_y + (vertical_offset * i) }, text_scale, { 255, 0, 0 });
	}

	





	// Display the cursor next to the option
	std::string output = "=";
	/*
	const char* output = "";
	int length = 0;
	if (m_nCursor == MenuItems::PLAY_GAME)
	{
		output = "=         =";
		length = 9;
	}
	else if (m_nCursor == MenuItems::HOW_TO_PLAY)
	{
		output = "=           =";
		length = 11;
	}
	else if (m_nCursor == MenuItems::OPTIONS || m_nCursor == MenuItems::CREDITS)
	{
		output = "=       =";
		length = 7;
	}
	else if (m_nCursor == MenuItems::EXIT)
	{
		output = "=    =";
		length = 4;
	}

	pFont->Draw( output, { (width - (length * 32))/2 - 32.0F, 300.0f + 50*m_nCursor }, 1.0f, {0, 255, 0} );
	*/
	/*
	for (int i = 0; i < stringlengths[m_nCursor]; i++)
		output += " ";
	output += "=";
	*/
	pFont->Draw(output.c_str(), { starting_x - 32.0F, starting_y + offset * m_nCursor - 8.0f }, 1.0f, { 0, 255, 0 });


	// Draw the reticle
	SGD::Point mousepos	= SGD::InputManager::GetInstance()->GetMousePosition();

	SGD::Point	retpos	= mousepos;
	float		retscale = 0.8f;
	retpos.Offset(-32.0F * retscale, -32.0F * retscale);

	pGraphics->DrawTexture(m_hReticleImage, retpos, 0.0F, {}, { 255, 255, 255 }, { retscale, retscale });


	// filled rects
	/*
	for (size_t i = 0; i < NUM_CHOICES; i++)
	{
		if (mousepos.IsWithinRectangle(selectonrects[i]) == true)
			pGraphics->DrawRectangle(selectonrects[i], { 128, 255, 0, 0 });
	}
	*/
	

}